<?php
namespace app\Tools;

class WechatPay {



    protected $appid = ''; //小程序appid
    protected $mch_id = ''; //商户号
    protected $notify_url = ''; //回调的url
    protected $key = ''; //商户秘钥 key



    public function __construct($options=[])
    {
        $this->appid = isset($options['appid'])?$options['appid']:'';
        $this->mch_id = isset($options['mch_id'])?$options['mch_id']:'';
        $this->notify_url = isset($options['notify_url'])?$options['notify_url']:'';
        $this->key = isset($options['key'])?$options['key']:'';
    }


    //企业付款到零钱
    public function toPay($nonce_str,$partner_trade_no,$openid,$money,$body,$cert,$check_name='NO_CHECK'){

        $data['mch_appid'] = $this->appid;//appid
        $data['mchid'] = $this->mch_id;//商户号
        $data['nonce_str'] = $nonce_str;//随机字符串
        $data['partner_trade_no'] = $partner_trade_no;//商户订单号	需保持唯一性
        $data['openid'] = $openid;//用户openid
        $data['check_name'] = $check_name;/////NO_CHECK：不校验真实姓名 , FORCE_CHECK：强校验真实姓名
        $data['amount'] = $money;//企业付款金额，单位为分
        $data['desc'] = $body;//企业付款备注
        $data['spbill_create_ip'] = $this->getIp(); //Ip地址

        $data['sign'] = $this->sign($data);
        $xml = $this->arrayToXml($data);
        $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';
        $res = $this->curl_post_ssl($url, $xml,$cert);

        return $this->xmlToArray($res);
    }



    //  统一下单
    public function unifiedOrder($data){

        $order['appid']              = $this->appid;
        $order['mch_id']             = $this->mch_id;
        $order['body']               = $data['body']; //支付描述
        $order['out_trade_no']       = $data['out_trade_no']; //商户系统内部订单号，要求32个字符内
        $order['total_fee']          = $data['total_fee']; //总价，需要 * 100
        $order['notify_url']         = $this->notify_url; //异步接收微信支付结果通知的回调地址
        $order['openid']             = $data['openid']; //客户的openid 公众号支付必须参数，通过登录即可获取
        $order['nonce_str']          = uniqid();//随机数
        $order['spbill_create_ip']   = $this->getIp();
        $order['trade_type']         = 'JSAPI';

        $order['sign']               = $this->sign($order);

        $xml = $this->arrayToXml($order);
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $res = $this->curlPost($url, $xml);
        $arr = $this->xmlToArray($res);
        if($arr['return_code'] == 'FAIL'){return false;}
        if($arr['result_code'] == 'FAIL'){return false;}

        //返回前端所需的支付数据
        $arrPay                     = array();
        $arrPay['appId']            = $order['appid'];
        $timeStamp        = time();
        $arrPay['timeStamp']        = "$timeStamp";
        $arrPay['nonceStr']         = uniqid();
        $arrPay['package']          = "prepay_id=".$arr['prepay_id'];
        $arrPay['signType']         = "MD5";
        $arrPay['paySign']          = $this->sign($arrPay);

        return $arrPay;
    }

    /*
     *  "appId"       :
        "timeStamp"   :
        "nonceStr"    :
        "package"     :
        "paySign"     :
    */

    public function getAppPayParams($order){

        $data['appId'] = $this->appid;
        $data['timestamp'] = time();///时间戳
        $data['nonceStr'] = $order['nonce_str'];//随机字符串
        $data['package'] = "prepay_id=".$order['prepay_id'];//预支付交易会话ID 即订单号
        $data['signType'] = "MD5";
        $data['sign'] = $this->sign( $data );//签名
        return $data;
    }

    public function sign($array){
        ksort($array);
        $string = '';
        foreach ($array as $k => $v){
            if($k != "sign" && $v != "" && !is_array($v)){$string .= $k . "=" . $v . "&";}
        }
        $string = trim($string, "&");
        $string = $string . "&key=".$this->key;
        $string = md5($string);
        $result = strtoupper($string);
        return $result;
    }


    public function getIp() {
        if(isset($_SERVER)){
            if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
                $arr = explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']);
                foreach ($arr as $ip){
                    $ip = trim($ip);
                    if ($ip != 'unknown'){$realip = $ip; break;}
                }
            }elseif(isset($_SERVER['HTTP_CLIENT_IP'])){
                $realip = $_SERVER['HTTP_CLIENT_IP'];
            }else{
                if (isset($_SERVER['REMOTE_ADDR'])){
                    $realip = $_SERVER['REMOTE_ADDR'];
                }else{
                    $realip = '0.0.0.0';
                }
            }
        }else{
            if (getenv('HTTP_X_FORWARDED_FOR')){
                $realip = getenv('HTTP_X_FORWARDED_FOR');
            }elseif (getenv('HTTP_CLIENT_IP')){
                $realip = getenv('HTTP_CLIENT_IP');
            }else{
                $realip = getenv('REMOTE_ADDR');
            }
        }
        preg_match("/[\d\.]{7,15}/",$realip,$onlineip);
        $realip = !empty($onlineip[0]) ? $onlineip[0] : '0.0.0.0';
        return $realip;
    }

    public function arrayToXml($arr){
        $xml = '<xml>';
        foreach($arr as $key => $val){
            if (is_numeric($val)){
                $xml.="<".$key.">".$val."</".$key.">";
            }else{
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            }
        }
        $xml .= '</xml>';
        return $xml;
    }

    //xml转数组函数
    public function xmlToArray($xml){
        libxml_disable_entity_loader(true);
        $arr = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $arr;
    }

    public function curlPost($url, $data){
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER , true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER , false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST , false);
        curl_setopt($ch, CURLOPT_POST           , 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS     , $data);
        curl_setopt($ch, CURLOPT_ENCODING       , 'gzip,deflate');
        $res  = curl_exec($ch);
        curl_close($ch);
        return $res;
    }



    public function curl_post_ssl($url, $xmldata, $cert, $second=30,$aHeader=array()){
        $ch = curl_init();
        //超时时间
        curl_setopt($ch,CURLOPT_TIMEOUT,$second);
        curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch,CURLOPT_URL,$url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);
        curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');//证书默认格式为PEM
        curl_setopt($ch,CURLOPT_SSLCERT,$cert['cert_path']);//证书位置
        curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');//证书秘钥默认格式为PEM
        curl_setopt($ch,CURLOPT_SSLKEY,$cert['key_path']);//证书秘钥位置
        if( count($aHeader) >= 1 ){
            curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
        }
        curl_setopt($ch,CURLOPT_POST, 1);
        curl_setopt($ch,CURLOPT_POSTFIELDS,$xmldata);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }

}